import {reactive, ReactiveFlags} from "./reactive.js";
import {activeEffect} from "./effect.js";
import {isObject} from "../shared/index.js";

export const mutableHandlers = {
    // 原始对象 属性 代理对象
    get(target, key, receiver) {
        // 走到这里说明已经是代理对象, 可返回true
        if (key === ReactiveFlags.IS_REACTIVE) {
            return true;
        }
        // console.log('取值的时候关联effect')
        track(target, key);

        let result = Reflect.get(target, key, receiver);
        if (isObject(result)) {
            // 如果对象的属性内有对象， 我们也应该针对于这个对象进行代理。这也是一个懒代理，也就是说只有读取到这个属性才进行代理，还没被读取的时候是不进行代理的。
            return reactive(result);
        }
        return result;
    },
    set(target, key, value, receiver) {
        // console.log('设置值的时候，触发更新')
        let oldValue = target[key];
        let flag = Reflect.set(target, key, value, receiver);
        if (oldValue !== value) {
            trigger(target, key, value, oldValue);
        }
        return flag;
    },
};

// Map1 = {({name: 'jw',age:30}):Map2}
// Map2 = {name: new Set([effect, effect])}

// {name: 'jw',age:30} 对象内的 name 属性 对应了两个 effect [effect, effect]

const targetMap = new WeakMap();

// 收集依赖
function track(target, key) {
    if (activeEffect) {
        // 当前属性在 effect 中使用我才收集，否则不收集
        let depsMap = targetMap.get(target);
        if (!depsMap) {
            targetMap.set(target, (depsMap = new Map()));
        }

        let dep = depsMap.get(key);
        if (!dep) {
            depsMap.set(key, (dep = new Set()));
        }
        trackEffects(dep)
    }
}

export function trackEffects(dep) {
    let shouldTrack = !dep.has(activeEffect);
    if (shouldTrack) {
        dep.add(activeEffect);

        // name = new Set(effect)
        // age = new Set(effect)

        // 我可以通过当前的effect 找到这两个集合中的自己。将其移除掉就可以了
        activeEffect.deps.push(dep);
    }
}

// 触发依赖
function trigger(target, key, value, oldValue) {
    let depsMap = targetMap.get(target);
    if (!depsMap) {
        return;
    }
    let effects = depsMap.get(key);
    triggerEffects(effects)

}

export function triggerEffects(dep) {
    const effects = [...dep];
    // 运行的是数组 删除的是set
    effects &&
    effects.forEach((effect) => {
        // 正在执行的effect ，不要多次执行
        if (effect !== activeEffect) {
            if (effect.scheduler) {
                effect.scheduler(); // 用户传递了对应的更新函数则调用此函数
                // 如果用户没有传递则默认就是重新运行effect函数
            } else {
                effect.run();
            }
        }
    });
}



